import * as AxiosRequest from './axios';
import {flow} from "mobx";
import {CancellablePromise, FlowReturnType} from "mobx/lib/api/flow";

declare type CancelFlowRequest<ReturnType> = CancellablePromise<FlowReturnType<ReturnType>>;

const FlowRequestList: Array<CancelFlowRequest<any>> = [];

/* flow-axios.ts
*  注解：
*   1. 调用方式以async/await为主
*   2. 实现方式采用了yield
*   3. 在取消请求时将会抛出FLOW_CANCEL的异常，/
*      有需要可通过this.setState来将异常回返到ComponentDidCatch接收
*   4. ReturnType 为一般接口返回的模型
*/

export function flowRequest<ReturnType>(url: string, options?: AxiosRequest.IAxiosRequestExtendConfig): CancelFlowRequest<ReturnType> {
    let requestPromise: AxiosRequest.IAxiosRequestPromise<ReturnType>;
    let promise: CancelFlowRequest<ReturnType> = flow<ReturnType, any[]>(function* () {
        requestPromise = AxiosRequest.request<ReturnType>(url, options);
        return yield requestPromise;
    })();

    let baseCancel = promise.cancel;
    FlowRequestList.push(promise);

    promise.cancel = function () {
        let index = FlowRequestList.indexOf(promise);
        if (index >= 0) {
            FlowRequestList.splice(index, 1);
        }
        if (requestPromise !== null && requestPromise !== undefined) {
            if (typeof requestPromise.cancel === 'function') {
                requestPromise.cancel();
            }
        }
        baseCancel.call(promise);
    };

    return promise;
}

export function abortEveryRequest() {
    FlowRequestList
        .splice(0, FlowRequestList.length)
        .forEach(promise => promise.cancel());
}

